package com.lifeverse.controller;

import com.lifeverse.common.ApiResponse;
import com.lifeverse.entity.DigitalDNA;
import com.lifeverse.service.DigitalDNAService;
import com.lifeverse.service.FeatureMapper;
import com.lifeverse.service.GeneExpressionEngine;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.Map;
import java.util.Optional;

/**
 * 数字DNA控制器
 * 提供DNA管理的REST API接口
 */
@Slf4j
@RestController
@RequestMapping("/api/v1/dna")
@RequiredArgsConstructor
@Validated
@Tag(name = "数字DNA管理", description = "数字DNA的创建、查询、更新、表达和变异等操作")
public class DigitalDNAController {
    
    private final DigitalDNAService digitalDNAService;
    private final GeneExpressionEngine geneExpressionEngine;
    private final FeatureMapper featureMapper;
    
    /**
     * 创建新的数字DNA
     */
    @PostMapping
    @Operation(summary = "创建数字DNA", description = "为指定生命体创建新的数字DNA")
    public ResponseEntity<ApiResponse<DigitalDNA>> createDNA(
            @Parameter(description = "生命体ID", required = true)
            @RequestParam @NotNull @Min(1) Long lifeEntityId,
            @Parameter(description = "基因数据", required = true)
            @RequestBody @Valid Map<String, Object> geneData) {
        
        log.info("Creating DNA for life entity: {}", lifeEntityId);
        
        DigitalDNA dna = digitalDNAService.createDNA(lifeEntityId, geneData);
        return ResponseEntity.ok(ApiResponse.success(dna));
    }
    
    /**
     * 根据ID查询DNA
     */
    @GetMapping("/{id}")
    @Operation(summary = "查询DNA", description = "根据ID查询指定的数字DNA")
    public ResponseEntity<ApiResponse<DigitalDNA>> getDNA(
            @Parameter(description = "DNA ID", required = true)
            @PathVariable @NotNull @Min(1) Long id) {
        
        Optional<DigitalDNA> dna = digitalDNAService.findById(id);
        if (dna.isPresent()) {
            return ResponseEntity.ok(ApiResponse.success(dna.get()));
        } else {
            return ResponseEntity.ok(ApiResponse.error("DNA不存在"));
        }
    }
    
    /**
     * 根据生命体ID查询DNA
     */
    @GetMapping("/life-entity/{lifeEntityId}")
    @Operation(summary = "根据生命体查询DNA", description = "根据生命体ID查询对应的数字DNA")
    public ResponseEntity<ApiResponse<DigitalDNA>> getDNAByLifeEntity(
            @Parameter(description = "生命体ID", required = true)
            @PathVariable @NotNull @Min(1) Long lifeEntityId) {
        
        Optional<DigitalDNA> dna = digitalDNAService.findByLifeEntityId(lifeEntityId);
        if (dna.isPresent()) {
            return ResponseEntity.ok(ApiResponse.success(dna.get()));
        } else {
            return ResponseEntity.ok(ApiResponse.error("该生命体没有DNA"));
        }
    }
    
    /**
     * 分页查询高适应度DNA
     */
    @GetMapping("/high-fitness")
    @Operation(summary = "查询高适应度DNA", description = "分页查询适应度高于指定阈值的DNA")
    public ResponseEntity<ApiResponse<Page<DigitalDNA>>> getHighFitnessDNA(
            @Parameter(description = "最小适应度", required = true)
            @RequestParam @NotNull BigDecimal minFitness,
            @Parameter(description = "页码", example = "0")
            @RequestParam(defaultValue = "0") int page,
            @Parameter(description = "页大小", example = "10")
            @RequestParam(defaultValue = "10") int size,
            @Parameter(description = "排序字段", example = "fitnessScore")
            @RequestParam(defaultValue = "fitnessScore") String sortBy,
            @Parameter(description = "排序方向", example = "desc")
            @RequestParam(defaultValue = "desc") String sortDir) {
        
        Sort sort = Sort.by(Sort.Direction.fromString(sortDir), sortBy);
        Pageable pageable = PageRequest.of(page, size, sort);
        
        Page<DigitalDNA> dnaPage = digitalDNAService.findHighFitnessDNA(minFitness, pageable);
        return ResponseEntity.ok(ApiResponse.success(dnaPage));
    }
    
    /**
     * 更新DNA
     */
    @PutMapping("/{id}")
    @Operation(summary = "更新DNA", description = "更新指定DNA的基因信息")
    public ResponseEntity<ApiResponse<DigitalDNA>> updateDNA(
            @Parameter(description = "DNA ID", required = true)
            @PathVariable @NotNull @Min(1) Long id,
            @Parameter(description = "更新数据", required = true)
            @RequestBody @Valid Map<String, Object> updateData) {
        
        log.info("Updating DNA: {}", id);
        
        DigitalDNA updatedDNA = digitalDNAService.updateDNA(id, updateData);
        return ResponseEntity.ok(ApiResponse.success(updatedDNA));
    }
    
    /**
     * 表达DNA基因
     */
    @PostMapping("/{id}/express")
    @Operation(summary = "表达DNA基因", description = "在指定环境条件下表达DNA基因")
    public ResponseEntity<ApiResponse<Map<String, Object>>> expressGenes(
            @Parameter(description = "DNA ID", required = true)
            @PathVariable @NotNull @Min(1) Long id,
            @Parameter(description = "环境条件", required = true)
            @RequestBody @Valid Map<String, Object> environment) {
        
        log.info("Expressing genes for DNA: {}", id);
        
        Map<String, Object> expressionResult = digitalDNAService.expressGenes(id, environment);
        return ResponseEntity.ok(ApiResponse.success(expressionResult));
    }
    
    /**
     * 预测基因表达
     */
    @PostMapping("/{id}/predict-expression")
    @Operation(summary = "预测基因表达", description = "预测DNA在指定环境下的基因表达结果")
    public ResponseEntity<ApiResponse<Map<String, Object>>> predictExpression(
            @Parameter(description = "DNA ID", required = true)
            @PathVariable @NotNull @Min(1) Long id,
            @Parameter(description = "环境条件", required = true)
            @RequestBody @Valid Map<String, Object> environment) {
        
        Optional<DigitalDNA> dnaOpt = digitalDNAService.findById(id);
        if (dnaOpt.isEmpty()) {
            return ResponseEntity.ok(ApiResponse.error("DNA不存在"));
        }
        
        Map<String, Object> prediction = geneExpressionEngine.predictExpression(dnaOpt.get(), environment);
        return ResponseEntity.ok(ApiResponse.success(prediction));
    }
    
    /**
     * 计算表达适应度
     */
    @PostMapping("/{id}/expression-fitness")
    @Operation(summary = "计算表达适应度", description = "计算DNA在指定环境下的表达适应度")
    public ResponseEntity<ApiResponse<BigDecimal>> calculateExpressionFitness(
            @Parameter(description = "DNA ID", required = true)
            @PathVariable @NotNull @Min(1) Long id,
            @Parameter(description = "环境条件", required = true)
            @RequestBody @Valid Map<String, Object> environment) {
        
        Optional<DigitalDNA> dnaOpt = digitalDNAService.findById(id);
        if (dnaOpt.isEmpty()) {
            return ResponseEntity.ok(ApiResponse.error("DNA不存在"));
        }
        
        BigDecimal fitness = geneExpressionEngine.calculateExpressionFitness(dnaOpt.get(), environment);
        return ResponseEntity.ok(ApiResponse.success(fitness));
    }
    
    /**
     * DNA变异
     */
    @PostMapping("/{id}/mutate")
    @Operation(summary = "DNA变异", description = "对指定DNA进行变异操作")
    public ResponseEntity<ApiResponse<DigitalDNA>> mutateDNA(
            @Parameter(description = "DNA ID", required = true)
            @PathVariable @NotNull @Min(1) Long id,
            @Parameter(description = "变异强度", example = "0.1")
            @RequestParam(defaultValue = "0.1") BigDecimal mutationIntensity) {
        
        log.info("Mutating DNA: {} with intensity: {}", id, mutationIntensity);
        
        DigitalDNA mutatedDNA = digitalDNAService.mutateDNA(id, mutationIntensity);
        return ResponseEntity.ok(ApiResponse.success(mutatedDNA));
    }
    
    /**
     * DNA交叉繁殖
     */
    @PostMapping("/crossover")
    @Operation(summary = "DNA交叉繁殖", description = "两个DNA进行交叉繁殖产生后代DNA")
    public ResponseEntity<ApiResponse<DigitalDNA>> crossoverDNA(
            @Parameter(description = "父DNA ID", required = true)
            @RequestParam @NotNull @Min(1) Long parentDnaId,
            @Parameter(description = "母DNA ID", required = true)
            @RequestParam @NotNull @Min(1) Long motherDnaId,
            @Parameter(description = "后代生命体ID", required = true)
            @RequestParam @NotNull @Min(1) Long offspringLifeEntityId) {
        
        log.info("Crossover DNA: parent={}, mother={}, offspring={}", 
                parentDnaId, motherDnaId, offspringLifeEntityId);
        
        DigitalDNA offspringDNA = digitalDNAService.crossoverDNA(parentDnaId, motherDnaId, offspringLifeEntityId);
        return ResponseEntity.ok(ApiResponse.success(offspringDNA));
    }
    
    /**
     * 计算DNA相似度
     */
    @GetMapping("/{id1}/similarity/{id2}")
    @Operation(summary = "计算DNA相似度", description = "计算两个DNA之间的相似度")
    public ResponseEntity<ApiResponse<BigDecimal>> calculateSimilarity(
            @Parameter(description = "第一个DNA ID", required = true)
            @PathVariable @NotNull @Min(1) Long id1,
            @Parameter(description = "第二个DNA ID", required = true)
            @PathVariable @NotNull @Min(1) Long id2) {
        
        BigDecimal similarity = digitalDNAService.calculateSimilarity(id1, id2);
        return ResponseEntity.ok(ApiResponse.success(similarity));
    }
    
    /**
     * 获取DNA特征向量
     */
    @GetMapping("/{id}/features")
    @Operation(summary = "获取DNA特征向量", description = "提取DNA的特征向量")
    public ResponseEntity<ApiResponse<Map<String, Double>>> getFeatureVector(
            @Parameter(description = "DNA ID", required = true)
            @PathVariable @NotNull @Min(1) Long id) {
        
        Optional<DigitalDNA> dnaOpt = digitalDNAService.findById(id);
        if (dnaOpt.isEmpty()) {
            return ResponseEntity.ok(ApiResponse.error("DNA不存在"));
        }
        
        Map<String, Double> features = featureMapper.extractFeatureVector(dnaOpt.get());
        return ResponseEntity.ok(ApiResponse.success(features));
    }
    
    /**
     * 获取DNA特征摘要
     */
    @GetMapping("/{id}/summary")
    @Operation(summary = "获取DNA特征摘要", description = "获取DNA的详细特征摘要")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getFeatureSummary(
            @Parameter(description = "DNA ID", required = true)
            @PathVariable @NotNull @Min(1) Long id) {
        
        Optional<DigitalDNA> dnaOpt = digitalDNAService.findById(id);
        if (dnaOpt.isEmpty()) {
            return ResponseEntity.ok(ApiResponse.error("DNA不存在"));
        }
        
        Map<String, Object> summary = featureMapper.generateFeatureSummary(dnaOpt.get());
        return ResponseEntity.ok(ApiResponse.success(summary));
    }
    
    /**
     * 删除DNA
     */
    @DeleteMapping("/{id}")
    @Operation(summary = "删除DNA", description = "删除指定的数字DNA")
    public ResponseEntity<ApiResponse<Void>> deleteDNA(
            @Parameter(description = "DNA ID", required = true)
            @PathVariable @NotNull @Min(1) Long id) {
        
        log.info("Deleting DNA: {}", id);
        
        digitalDNAService.deleteDNA(id);
        return ResponseEntity.ok(ApiResponse.success(null));
    }
    
    /**
     * 获取DNA统计信息
     */
    @GetMapping("/statistics")
    @Operation(summary = "获取DNA统计信息", description = "获取系统中所有DNA的统计信息")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getDNAStatistics() {
        Map<String, Object> statistics = digitalDNAService.getDNAStatistics();
        return ResponseEntity.ok(ApiResponse.success(statistics));
    }
    
    /**
     * 查询稳定的DNA
     */
    @GetMapping("/stable")
    @Operation(summary = "查询稳定DNA", description = "查询稳定性高于指定阈值的DNA")
    public ResponseEntity<ApiResponse<java.util.List<DigitalDNA>>> getStableDNA(
            @Parameter(description = "最小稳定性", example = "70.0")
            @RequestParam(defaultValue = "70.0") BigDecimal minStability) {
        
        java.util.List<DigitalDNA> stableDNA = digitalDNAService.findStableDNA(minStability);
        return ResponseEntity.ok(ApiResponse.success(stableDNA));
    }
    
    /**
     * 查询活跃的DNA
     */
    @GetMapping("/active")
    @Operation(summary = "查询活跃DNA", description = "查询表达活跃度高于指定阈值的DNA")
    public ResponseEntity<ApiResponse<java.util.List<DigitalDNA>>> getActiveDNA(
            @Parameter(description = "最小活跃度", example = "50.0")
            @RequestParam(defaultValue = "50.0") BigDecimal minActivity) {
        
        java.util.List<DigitalDNA> activeDNA = digitalDNAService.findActiveDNA(minActivity);
        return ResponseEntity.ok(ApiResponse.success(activeDNA));
    }
}